#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <sys/types.h>
#include <sys/stat.h>
#include <vector>
#include <fstream>
#include <algorithm>
#include <sstream>

using namespace std;

class bSphere
{
	public:
		int id;
		string mac_address;
		string event;
		string action;
};


// Function Prototypes
std::string run_command(string cmd);
std::string trim(std::string &str);
void Split(string str, string delim, vector<string> &results);
void lcase(string &str);
void getSpheres(vector<bSphere> &tmpSpheres);

// Entry Point
int main(int argc, char **argv)
{
/*
        // Start The Daemonization Process
        pid_t this_pid = fork();
        if (this_pid < 0) exit(1);
        if (this_pid > 0) exit(0);


        // If We Are The Child (Now Main) Pid, Set rwx
        umask(0);


        // Become An Emancipated Minor
        pid_t sid;
        sid = setsid();
        if (sid < 0) {
                // log error
                exit(1);
        }

        if ((chdir("/")) < 0) {
                // log error
                exit(1);
        }

        // We're A Daemon, We Don't Need These
	close(STDIN_FILENO);
	close(STDOUT_FILENO);
	close(STDERR_FILENO);
*/
	string shell_data;
	string parts_data;
	vector<string> strParts;
	vector<string> addresses;

	vector<bSphere> spheres; 
	getSpheres(spheres);

	while (1) {
		strParts.clear();
		addresses.clear();

		shell_data = run_command("hcitool con");
		Split(shell_data, "\n", strParts);		

		for (int i=1; i < strParts.size(); i++) {
			parts_data = trim(strParts[i]);

			if (parts_data[0] == '>') {
				shell_data = parts_data.substr(2);
			} else if (parts_data == "") {
				break;	
			} else {
				shell_data = parts_data;
			}

			vector<string> xparts;
			Split(shell_data, " ", xparts);

			string mac_address = xparts[1];
			addresses.push_back(mac_address);
		}

		for (int i=0; i < spheres.size(); i++) {
			cout << spheres[i].id << endl;
			cout << spheres[i].mac_address << endl;
			cout << spheres[i].event << endl;
			cout << spheres[i].action << endl;
		}

        	sleep(5);
        }

        return 0;

}

void lcase(string &str)
{
	for (int i=0; i < str.length(); i++) {
		str[i] = tolower(str[i]);
	}

	return;
}


void getSpheres(vector<bSphere> &tmpSpheres)
{
	ifstream conf_file ("/etc/bluesphere.conf");
	if (!conf_file) {
		cout << "Missing configuration file: /etc/bluesphere.conf" << endl;
		exit(1);
	}

	if (conf_file.is_open()) {
		string line = "";
		bool flag = false;

		bSphere *tmpSphere;

		while (getline(conf_file, line)) {
			lcase(line);
	
			if (line == "<sphere>") {
				flag = true;
				tmpSphere = new bSphere();
			} else if (line == "</sphere>") {
				flag = false;
				tmpSpheres.push_back(*tmpSphere);
				delete tmpSphere;
			} else {
				if (flag) {
					vector<string> parts;
					Split(line, "=", parts);

					parts[0] = trim(parts[0]);
					parts[1] = trim(parts[1]);

					if (parts[0] == "id") {
						int num;
						istringstream(parts[1] ) >> num;
						tmpSphere->id = num;
					} else if (parts[0] == "mac_address") {
						string tmp = parts[1];
						tmpSphere->mac_address = tmp;
					} else if (parts[0] == "event") {
						tmpSphere->event = parts[1];
					} else if (parts[0] == "action") {
						tmpSphere->action = parts[1];
					}
				}
			}
		}
		conf_file.close();
	} else {
		cout << "Problem reading configuration file: /etc/bluesphere.conf" << endl;
		exit(1);
	}

	return;
}

string run_command(string cmd)
{
        string data;
        FILE *stream;
        char buffer[1024];             // Subject To Buffer Overflow Attacks

        stream = popen(cmd.c_str(), "r");
        while (fgets(buffer, 1024, stream) != NULL) {
                data.append(buffer);
        }
        pclose(stream);

        return data;
}

void Split(string str, string delim, vector<string> &results)
{
        string tmpresult;
        results.clear();

        // Loop For Each Character In The String 
        for (int i=0; i < (int)str.size(); i++) {
                if (str[i] == delim[0]) {

                        // The String Matches The Delimeter
                        results.push_back(tmpresult);
                        tmpresult.clear();

                } else {

                        tmpresult += str[i];

                }
        }

        // Stick The Remaining String Into The Vector
        results.push_back(tmpresult);
}

string trim(std::string &str)
{
	str.erase(0, str.find_first_not_of('\n'));
	str.erase(0, str.find_first_not_of('\t'));
	str.erase(0, str.find_first_not_of(' '));
	str.erase(str.find_last_not_of(' ')+1);
	str.erase(str.find_last_not_of('\n') +1);
	return str;
}
